package com.fitso.model.calculator.idealweight;

import org.springframework.util.Assert;

import com.fitso.model.bean.Body;
import com.fitso.model.bean.measure.length.Inch;
import com.fitso.model.bean.measure.length.Length;
import com.fitso.model.bean.measure.mass.KiloGram;
import com.fitso.model.bean.measure.mass.Mass;
import com.fitso.model.calculator.IdealWeightCalculator;

/**
 * Base class used to calculate ideal body weight with a common equation. All
 * that changes are equation constants
 * 
 * @author timothystorm
 * 
 */
public abstract class AbstractIdealWeightCalculator implements IdealWeightCalculator {
	/**
	 * Calculates ideal body weight by adding a mass unit to a base weight for
	 * each unit over a base height (bw + (wm * (h-bh)) : bw->base weight, wm ->
	 * weight multiplier, h -> height, bh -> base height
	 */
	public Mass calculate(Body body) {
		Assert.notNull(body, "body required"); // ghosts don't have an ideal

		KiloGram weight = new KiloGram(getRootWeight(body));
		KiloGram weightMultiplier = new KiloGram(getWeightMultiplier(body));
		Inch height = new Inch(body.getHeight());
		Inch medianHeight = new Inch(getMedianHeight(body));

		if (height.compareTo(medianHeight) >= 0) {
			return new KiloGram(weight.add(weightMultiplier.multiply(height.subtract(medianHeight))).getValue());
		}
		return new KiloGram(weight.getValue());
	}

	protected abstract Mass getRootWeight(Body body);

	protected abstract Mass getWeightMultiplier(Body body);

	protected abstract Length getMedianHeight(Body body);
}
